package edu.ynu.se.xiecheng.achitectureclass.demo.scheduler;

import edu.ynu.se.xiecheng.achitectureclass.demo.config.HttpClientConfig;
import edu.ynu.se.xiecheng.achitectureclass.demo.entity.Device;
import edu.ynu.se.xiecheng.achitectureclass.demo.entity.data.SensorData;
import edu.ynu.se.xiecheng.achitectureclass.demo.entity.sensors.*;
import edu.ynu.se.xiecheng.achitectureclass.demo.factory.SensorDataFactory;
import edu.ynu.se.xiecheng.achitectureclass.demo.service.DeviceService;
import edu.ynu.se.xiecheng.achitectureclass.demo.service.SensorDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class SensorDataScheduler {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private SensorDataService sensorDataService;
    @Autowired
    private HttpClientConfig httpClientConfig;

    private static Map<Integer, String> sensorTypeMap;

    static {
        sensorTypeMap = new HashMap<>();
        sensorTypeMap.put(1, "soilmoisture_sensor");
        sensorTypeMap.put(2, "soiltemperature_sensor");
        sensorTypeMap.put(3, "soilconductivity_sensor");
        sensorTypeMap.put(4, "soilphvalue_sensor");
        sensorTypeMap.put(5, "soilnitrogencontent_sensor");
        sensorTypeMap.put(6, "soilphosphoruscontent_sensor");
        sensorTypeMap.put(7, "soilpotassiumcontent_sensor");
        sensorTypeMap.put(8, "airtemperature_sensor");
        sensorTypeMap.put(9, "airrelativehumidity_sensor");
        sensorTypeMap.put(10, "illuminance_sensor");
        sensorTypeMap.put(11, "carbondioxide_sensor");
    }

    private static final Map<Integer, String> sensorTypeToFactoryClassMap = new HashMap<>();

    static {
        sensorTypeToFactoryClassMap.put(1, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilMoistureSensorFactory");
        sensorTypeToFactoryClassMap.put(2, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilTemperatureSensorFactory");
        sensorTypeToFactoryClassMap.put(3, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilConductivitySensorFactory");
        sensorTypeToFactoryClassMap.put(4, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilPHValueSensorFactory");
        sensorTypeToFactoryClassMap.put(5, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilNitrogenContentSensorFactory");
        sensorTypeToFactoryClassMap.put(6, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilPhosphorusContentSensorFactory");
        sensorTypeToFactoryClassMap.put(7, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.SoilPotassiumContentSensorFactory");
        sensorTypeToFactoryClassMap.put(8, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.AirTemperatureSensorFactory");
        sensorTypeToFactoryClassMap.put(9, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.AirRelativeHumiditySensorFactory");
        sensorTypeToFactoryClassMap.put(10, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.IlluminanceSensorFactory");
        sensorTypeToFactoryClassMap.put(11, "edu.ynu.se.xiecheng.achitectureclass.demo.factory.CarbonDioxideSensorFactory");
    }
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Scheduled(fixedRate = 10000)
    public void getAndStoreSensorData() {
        List<Device> devices = deviceService.findAllDevicesByType("sensor");
        List<String> deviceSerialNumbers = new ArrayList<>();
        for (Device device : devices) {
            if (device.getSerialNumber() != null) {
                deviceSerialNumbers.add(device.getSerialNumber());
            }else {
                throw new RuntimeException("Device serial number is null");
            }
        }

        Map<String, List<String>> params = new HashMap<>();
        params.put("ids", deviceSerialNumbers);
        Map<String, String> tokenMap = sensorDataService.getSensorToken();
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(tokenMap.get("access_token"));
        headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, List<String>>> request = new HttpEntity<>(params, headers);

        try {
            ResponseEntity<List> response = httpClientConfig.restTemplate().postForEntity("https://fbox360.com/api/v2/dmon/value/get?boxNo=300023040085", request, List.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                List<Map<String, Object>> responseBody = response.getBody();
                // 处理响应数据并存储
                for (Map<String, Object> map : responseBody) {
                    Device device = deviceService.findDeviceBySerialNumber(map.get("id").toString());
                    SensorDataFactory sensorDataFactory = getFactory(device.getId().intValue());
                    SensorData sensorData = sensorDataFactory.createSensorData();
                    sensorData.setDevice(device);
                    sensorData.setSensorType(map.get("name").toString());
                    if (map.get("name").toString().equals("空气温度") || map.get("name").toString().equals("空气相对湿度")){
                        sensorData.setValue(Double.parseDouble(map.get("value").toString()) / 10);
                    }
                    else{
                        sensorData.setValue(Double.parseDouble(map.get("value").toString()));
                    }
                    sensorDataService.POST(sensorData);
                    jdbcTemplate.update("INSERT INTO " + sensorTypeMap.get(device.getId().intValue()) + " (device_id, value, create_time, update_time) VALUES (?, ?, ?, ?)",
                                                                                                    device.getId(), sensorData.getValue(), LocalDateTime.now(), LocalDateTime.now());
                }
            } else {
                throw new RuntimeException("Failed to fetch sensor data: " + response.getStatusCode());
            }
        } catch (Exception e) {
            throw new RuntimeException("Error fetching sensor data: " + e.getMessage());
        }
    }

    public static SensorDataFactory getFactory(int sensorType) {
        String factoryClassName = sensorTypeToFactoryClassMap.get(sensorType);
        if (factoryClassName == null) {
            throw new IllegalArgumentException("Unknown sensor type: " + sensorType);
        }
        try {
            Class<?> factoryClass = Class.forName(factoryClassName);
            return (SensorDataFactory) factoryClass.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Error creating factory: " + e.getMessage(), e);
        }
    }
}